package cn.wushige;

import org.activiti.engine.*;
import org.activiti.engine.history.HistoricDetail;
import org.activiti.engine.history.HistoricFormProperty;
import org.activiti.engine.history.HistoricProcessInstance;
import org.activiti.engine.history.HistoricVariableUpdate;
import org.activiti.engine.repository.ProcessDefinition;
import org.activiti.engine.runtime.ProcessInstance;
import org.activiti.engine.task.Task;
import org.activiti.engine.test.ActivitiRule;
import org.activiti.engine.test.Deployment;
import org.junit.Before;
import org.junit.Rule;
import org.junit.Test;

import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import static junit.framework.TestCase.assertNotNull;
import static org.junit.Assert.assertEquals;

public class ProcessTestLeaveformkey {

	private RepositoryService repositoryService;
	private RuntimeService runtimeService;
	private TaskService taskService;
	private FormService formService;
	private IdentityService identityService;
	private HistoryService historyService;

	@Rule
	public ActivitiRule activitiRule = new ActivitiRule();

	@Before
	public void setUp() {
		repositoryService = activitiRule.getRepositoryService();
		runtimeService = activitiRule.getRuntimeService();
		taskService = activitiRule.getTaskService();
		formService = activitiRule.getFormService();
		identityService = activitiRule.getIdentityService();
		historyService = activitiRule.getHistoryService();
	}

	@Test
	@Deployment(resources = {"processes/leave-formkey.bpmn", "processes/leave-start.form",
			"processes/approve-deptLeader.form", "processes/approve-hr.form", "processes/report-back.form",
			"processes/modify-apply.form"})
	public void startProcess() throws Exception {
//		repositoryService.createDeployment().addClasspathResource("processes/leave-formkey.bpmn").deploy();
		SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
		Map<String, String> variables = new HashMap<>();
		Calendar ca = Calendar.getInstance();
		String startDate = sdf.format(ca.getTime());
		ca.add(Calendar.DAY_OF_MONTH, 2); // 当前日期加2天
		String endDate = sdf.format(ca.getTime());

		// 启动流程
		variables.put("startDate", startDate);
		variables.put("endDate", endDate);
		variables.put("reason", "公休");

		ProcessDefinition processDefinition = repositoryService.createProcessDefinitionQuery().singleResult();

		// 读取启动表单
		Object renderedStartForm = formService.getRenderedStartForm(processDefinition.getId());
		assertNotNull(renderedStartForm);

		// 启动流程
		// 设置当前用户
		String currentUserId = "henryyan";
		identityService.setAuthenticatedUserId(currentUserId);
		ProcessInstance processInstance = formService.submitStartFormData(processDefinition.getId(), variables);
		assertNotNull(processInstance);

		// 部门领导审批通过
		Task deptLeaderTask = taskService.createTaskQuery().taskCandidateGroup("deptLeader").singleResult();
		assertNotNull(formService.getRenderedTaskForm(deptLeaderTask.getId()));
		variables = new HashMap<>();
		variables.put("deptLeaderApproved", "true");
		formService.submitTaskFormData(deptLeaderTask.getId(), variables);

		// 人事审批通过
		Task hrTask = taskService.createTaskQuery().taskCandidateGroup("hr").singleResult();
		assertNotNull(formService.getRenderedTaskForm(hrTask.getId()));
		variables = new HashMap<>();
		variables.put("hrApproved", "true");
		formService.submitTaskFormData(hrTask.getId(), variables);

		// 销假（根据申请人的用户ID读取）
		Task reportBackTask = taskService.createTaskQuery().taskAssignee(currentUserId).singleResult();
		assertNotNull(formService.getRenderedTaskForm(reportBackTask.getId()));
		variables = new HashMap<>();
		variables.put("reportBackDate", sdf.format(ca.getTime()));
		formService.submitTaskFormData(reportBackTask.getId(), variables);

		// 验证流程是否已经结束
		HistoricProcessInstance historicProcessInstance = historyService.createHistoricProcessInstanceQuery().finished().singleResult();
		assertNotNull(historicProcessInstance);

		// 读取历史变量
		Map<String, Object> historyVariables = packageVariables(processInstance);

		// 验证执行结果
		assertEquals("ok", historyVariables.get("result"));
	}

	private Map<String, Object> packageVariables(ProcessInstance processInstance) {
		Map<String, Object> historyVariables = new HashMap<>();
		List<HistoricDetail> list = historyService.createHistoricDetailQuery().processInstanceId(processInstance.getId()).list();
		for (HistoricDetail historicDetail : list) {
			if (historicDetail instanceof HistoricFormProperty) {
				// 表单中的字段
				HistoricFormProperty field = (HistoricFormProperty) historicDetail;
				historyVariables.put(field.getPropertyId(), field.getPropertyValue());
				System.out.println("form field: taskId=" + field.getTaskId() + ", " + field.getPropertyId() + " = " + field.getPropertyValue());
			} else if (historicDetail instanceof HistoricVariableUpdate) {
				HistoricVariableUpdate variable = (HistoricVariableUpdate) historicDetail;
				historyVariables.put(variable.getVariableName(), variable.getValue());
				System.out.println("variable: " + variable.getVariableName() + " = " + variable.getValue());
			}
		}
		return historyVariables;
	}

}